package com.bbex.controller;

import com.bbex.config.sercurity.RedisSessionUser;
import com.bbex.constant.Constants;
import com.bbex.constant.SercurityConstant;
import com.bbex.entity.Coin;
import com.bbex.entity.PlatUser;
import com.bbex.enums.HidCoinTypeEnum;
import com.bbex.mapper.CoinDao;
import com.bbex.pojo.GlobalMessageResponseVo;
import com.bbex.service.*;
import com.bbex.util.JsonUtils;
import com.bbex.util.RsaUtils;
import com.bbex.vo.ActivateVO;
import com.bbex.vo.DivideintoLogListVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/bbuni")
public class ActivateHidController {

    private static Logger logger = LoggerFactory.getLogger(ActivateHidController.class);

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    private PlatUserService platUserService;

    @Autowired
    private HongmengCoinVolumeService hongmengCoinVolumeService ;

    @Autowired
    private CoinAddressService coinAddressService;

    @Autowired
    private CoinDao coinDao;

    @Autowired
    private DictService dictService;

    @Autowired
    private DivideintoLogService divideintoLogService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Resource(name = "stringRedisTemplate")
    ValueOperations<String, String> valOpsStr;

    /**
     * 激活hid
     */
    @PostMapping("/user/activateHid")
    @Transactional
    public Mono<GlobalMessageResponseVo> activateHid(ActivateVO activateVO) {

        Mono<SecurityContext> context
                = ReactiveSecurityContextHolder.getContext();
        return context.filter(c -> Objects.nonNull(c.getAuthentication()))
                .map(s -> s.getAuthentication().getPrincipal())
                .cast(RedisSessionUser.class)
                .map(e -> {
                    if(StringUtils.isEmpty(activateVO.getHid())){
                        //return Mono.just(GlobalMessageResponseVo.newErrorInstance("请输入正确的hid地址"));
                        return GlobalMessageResponseVo.newErrorInstance("请输入正确的hid地址");
                    }
                    if(e.getHidstatus()==1){
                        //return Mono.just(GlobalMessageResponseVo.newErrorInstance("该账户已激活hid"));
                        return GlobalMessageResponseVo.newErrorInstance("该账户已激活hid");
                    }
                    //验证交易密码
                    if(StringUtils.isBlank(e.getExPassword())) {
                        return GlobalMessageResponseVo.newInstance(Constants.EX_PASSWORD,"请设置交易密码");
                    }
                    String decryPassword = RsaUtils.decryptByPrivateKey(activateVO.getExPassword(), RsaUtils.DEFAULT_PRIVATE_KEY);
                    if(StringUtils.isBlank(decryPassword)) {
                        return GlobalMessageResponseVo.newErrorInstance("请填写交易密码");
                    }
                    if(!passwordEncoder.matches(decryPassword, e.getExPassword())) {
                        return GlobalMessageResponseVo.newErrorInstance("交易密码不正确");
                    }
                    //设置交易密码验证码2小时失效
                    String authKeyEx = SercurityConstant.AUTH_USERNAME_REDIS_NAMESAPCE+"ex:" + e.getUsername();
                    valOpsStr.set(authKeyEx, SercurityConstant.AuthType.PASS_AUTH.getCode(), SercurityConstant.REDIS_EXPIRE_TIME_ONE_HOUR * 2, TimeUnit.SECONDS);
                    //根据币种符号获取币种
                    Coin coin = coinDao.findByName(HidCoinTypeEnum.HMC.getCode());
                    //邀请人分成
                    hongmengCoinVolumeService.userRoyalty(e.getId(),activateVO.getHid(),coin.getId(),coin.getName());
                    //更新用户
                    PlatUser platuser = platUserService.updateHmUser(e.getId(), coin.getParentId(), activateVO.getHid());
                    //更新redis数据
                    e.setHidstatus(platuser.getHidstatus());
                    stringRedisTemplate.opsForHash().put(SercurityConstant.SESSION_TOKEN_REDIS_NAMESAPCE + e.getToken(), SercurityConstant.SESSION_TOKEN_REDIS_USER, JsonUtils.toJson(e));

                    //return Mono.just(GlobalMessageResponseVo.newSuccessInstance("激活hid成功"));
                    return GlobalMessageResponseVo.newSuccessInstance("激活hid成功");
                });
    }

    /**
     * 获取激活HID所需HMC数值
     * @return
     */
    @PostMapping("/user/activatePremise")
    public GlobalMessageResponseVo getActivatePremise() {
        //查询激活所需HMC数值
        BigDecimal hmc = new BigDecimal(dictService.getDictListByItemCode("HIDScale", "volume").get("dictName").toString());
        return GlobalMessageResponseVo.newSuccessInstance(hmc);
    }

    /**
     * 分成记录列表
     * @return
     */
    @PostMapping("/user/divideintoLog")
    public Mono<GlobalMessageResponseVo> divideintoLog(DivideintoLogListVO divideintoLogListVO) {

        Mono<SecurityContext> context
                = ReactiveSecurityContextHolder.getContext();

        return context.filter(c -> Objects.nonNull(c.getAuthentication()))
                .map(s -> s.getAuthentication().getPrincipal())
                .cast(RedisSessionUser.class)
                .map(e -> {
                    String userId = e.getId();
                    divideintoLogListVO.setUserId(userId);
                    return GlobalMessageResponseVo.newSuccessInstance(divideintoLogService.findDivideintoLogPage(divideintoLogListVO));

                });
    }
}
